local module = {}
module.name = "DoomCooldownPulse"
module.Init = function()
    if not SCDB.modules[module.name] then return end
    if SCDB[module.name] == nil then SCDB[module.name] = {} end
    if SCDB[module.name]["FadeInTime"] == nil then SCDB[module.name]["FadeInTime"] = 0.3 end
    if SCDB[module.name]["FadeOutTime"] == nil then SCDB[module.name]["FadeOutTime"] = 0.2 end
    if SCDB[module.name]["MaxAlpha"] == nil then SCDB[module.name]["MaxAlpha"] = 1 end
    if SCDB[module.name]["AnimScale"] == nil then SCDB[module.name]["AnimScale"] = 1.5 end
    if SCDB[module.name]["IconSize"] == nil then SCDB[module.name]["IconSize"] = 90 end
    if SCDB[module.name]["HoldTime"] == nil then SCDB[module.name]["HoldTime"] = 0.5 end
    local opt = SCDB[module.name]
      
    local GetTime = GetTime
    local cooldowns, animating, watching = {}, {}, {}
    
    local fadeInTime, fadeOutTime, maxAlpha, animScale, iconSize, holdTime = opt.FadeInTime or 0.3, opt.FadeOutTime or 0.2, opt.MaxAlpha or 1, opt.AnimScale or 1.5, opt.IconSize or 90, opt.HoldTime or 0
    
    local DCP = CreateFrame("frame", "DCPMainFrame", UIParent)
    DCP.anchor = CreateFrame("frame", "DoomCooldownPulse_Anchor", UIParent)
    DCP:SetPoint("CENTER", DCP.anchor, "CENTER", 0, 0)
    DCP.anchor:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
    DCP.anchor:SetSize(36, 36)
    if UIMovableFrames then tinsert(UIMovableFrames, DCP.anchor) end
    DCP.tex = DCP:CreateTexture(nil, "BACKGROUND"); DCP.tex:SetAllPoints(DCP)
 
    local GetPetActionIndexByName = function(name) for i=1, NUM_PET_ACTION_SLOTS, 1 do if (GetPetActionInfo(i) == name) then return i end end return nil end
    local tcount = function(tab) local n = 0 for _ in pairs(tab) do n = n + 1 end return n end
 
    DCP:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED")
    DCP:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
    DCP:RegisterEvent("UNIT_PET")
    DCP:RegisterEvent("PLAYER_ENTERING_WORLD")
    DCP:SetScript("OnEvent", function(self, event, ...) 
        if event == "PLAYER_ENTERING_WORLD" then
        local inInstance,instanceType = IsInInstance()
            if inInstance and instanceType == "arena" then
                cooldowns = {}
                watching = {}
                self:SetScript("OnUpdate",nil)
            end
        elseif event == "COMBAT_LOG_EVENT_UNFILTERED" then
            local timestamp, eventType, hideCaster, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags, spellID = ...
            if (eventType == "SPELL_CAST_SUCCESS") then
                if (bit.band(sourceFlags,COMBATLOG_OBJECT_TYPE_PET) == COMBATLOG_OBJECT_TYPE_PET and bit.band(sourceFlags,COMBATLOG_OBJECT_AFFILIATION_MINE) == COMBATLOG_OBJECT_AFFILIATION_MINE) then
                    local name = GetSpellInfo(spellID)
                    local index = GetPetActionIndexByName(name)
                    if (index and not select(8,GetPetActionInfo(index))) then
                        watching[name] = {GetTime(),"pet",index}
                    elseif (not index and name) then
                        watching[name] = {GetTime(),"spell",name}
                    else
                        return
                    end
                    self:SetScript("OnUpdate", function(self, elapsed) self:OnUpdate(elapsed) end)
                end
            end
        elseif event == "UNIT_SPELLCAST_SUCCEEDED" then
            local unit,spell = ...
            if unit == "player" then
                watching[spell] = {GetTime(),"spell",spell}
                self:SetScript("OnUpdate", function(self, elapsed) self:OnUpdate(elapsed) end)
            end
        elseif event == "UNIT_PET" then
            if (HasPetUI()) then
                self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
            else
                self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
            end
        end
    end)
    
    hooksecurefunc("UseInventoryItem", function(slot)
        local item = GetItemInfo(GetInventoryItemLink("player",slot) or "")
        if item then watching[item] = {GetTime(),"inventory",slot} end
    end)
    
    hooksecurefunc("UseContainerItem", function(bag,slot)
        local item = GetItemInfo(GetContainerItemLink(bag,slot) or "")
        if item then watching[item] = {GetTime(),"container",bag,slot} end
    end)

    local runtimer = 0
    function DCP:OnUpdate(update)
        if not self.elapsed then self.elapsed = 0 end
        self.elapsed = self.elapsed + update
        if (self.elapsed > 0.01) then
            for i,v in pairs(watching) do
                if (GetTime() >= v[1] + 0.5) then
                    local start, duration, enabled, texture
                    if (v[2] == "spell") then
                        texture = GetSpellTexture(v[3])
                        start, duration, enabled = GetSpellCooldown(v[3])
                    elseif (v[2] == "inventory") then
                        texture = select(10,GetItemInfo(GetInventoryItemLink("player",v[3])))
                        start, duration, enabled = GetInventoryItemCooldown("player",v[3])
                    elseif (v[2] == "container") then
                        texture = select(10,GetItemInfo(GetContainerItemLink(v[3],v[4]) or ""))
                        start, duration, enabled = GetContainerItemCooldown(v[3],v[4])
                    elseif (v[2] == "pet") then
                        texture = select(3,GetPetActionInfo(v[3]))
                        start, duration, enabled = GetPetActionCooldown(v[3])
                    end
                    if (enabled ~= 0) then
                        if (duration and duration > 2.0 and texture) then
                            cooldowns[i] = { start, duration, texture }
                        end
                    end
                    if (not (enabled == 0 and v[2] == "spell")) then
                        watching[i] = nil
                    end
                end
            end
            
            for i,v in pairs(cooldowns) do
                local remaining = v[2]-(GetTime()-v[1])
                if (remaining <= 0) then
                    tinsert(animating, v[3])
                    cooldowns[i] = nil
                end
            end
            
            self.elapsed = 0
            if (#animating == 0 and tcount(watching) == 0 and tcount(cooldowns) == 0) then
                self:SetScript("OnUpdate",nil)
                return
            end
        end
        
        if (#animating > 0) then
            runtimer = runtimer + update
            if (runtimer > (fadeInTime + holdTime + fadeOutTime)) then
                tremove(animating,1)
                runtimer = 0
                DCP.tex:SetTexture(nil)
            else
                if (not DCP.tex:GetTexture()) then
                    DCP.tex:SetTexture(animating[1])
                end
                local alpha = maxAlpha
                if (runtimer < fadeInTime) then
                    alpha = maxAlpha * (runtimer / fadeInTime)
                elseif (runtimer >= fadeInTime + holdTime) then
                    alpha = maxAlpha - ( maxAlpha * ((runtimer - holdTime - fadeInTime) / fadeOutTime))
                end
                self:SetAlpha(alpha)
                local scale = iconSize+(iconSize*((animScale-1)*(runtimer/(fadeInTime+holdTime+fadeOutTime))))
                self:SetSize(scale, scale)
            end
        end
    end
    
end
tinsert(SuperClassic.modules, module) -- finish him!